package com.bot.nft.module.op.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bot.common.chainbo.ChainAccountInfo;
import com.bot.common.chainbo.TradingResultsInfo;
import com.bot.common.exception.CommonException;
import com.bot.dev.api.DevBlockChainApi;
import com.bot.nft.core.config.LogDescription;
import com.bot.nft.core.enums.chain.ChainLogEnum;
import com.bot.nft.core.enums.op.OpTCEnum;
import com.bot.nft.core.util.NftCodeUtil;
import com.bot.nft.module.chain.domain.ChainOptLogInfo;
import com.bot.nft.module.chain.mapper.ChainOptLogMapper;
import com.bot.nft.module.dc.domain.DcFlowLog;
import com.bot.nft.module.dc.domain.DcNftCert;
import com.bot.nft.module.dc.domain.DcNftInfo;
import com.bot.nft.module.dc.domain.bo.DcNftCertBo;
import com.bot.nft.module.dc.domain.vo.DcNftCertVo;
import com.bot.nft.module.dc.mapper.DcFlowLogMapper;
import com.bot.nft.module.dc.mapper.DcNftInfoMapper;
import com.bot.nft.module.dc.mapper.DcNftCertMapper;
import com.bot.nft.module.dc.service.IDcNftCertService;
import com.bot.nft.module.dc.service.IDcNftInfoService;
import com.bot.nft.module.mb.domain.MbUserInfo;
import com.bot.nft.module.mb.domain.vo.MbUserInfoVo;
import com.bot.nft.module.mb.mapper.IMbMemberMapper;
import com.bot.nft.module.op.domain.*;
import com.bot.nft.module.op.domain.bo.OpNftTreChestBo;
import com.bot.nft.module.op.domain.bo.OpTreChestInfoBo;
import com.bot.nft.module.op.domain.bo.OpTreChestPrizeBo;
import com.bot.nft.module.op.domain.vo.*;
import com.bot.nft.module.op.mapper.*;
import com.bot.nft.module.op.service.IOpTreChestService;
import com.fhs.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * 描述:宝箱活动业务接口实现
 * 时间: 2023-11-27 20:19
 * 负责人: 王康
 **/
@Service
@Slf4j
public class OpTreChestServiceImpl extends ServiceImpl<OpTreChestInfoMapper, OpTreChestInfo> implements IOpTreChestService {

    /**
     * 宝箱活动的mapper接口
     */
    @Resource
    public OpTreChestInfoMapper mapper;

    /**
     * 藏品抽奖消耗信息mapper接口
     */
    @Resource
    public OpNftTreChestMapper opNftTreChestMapper;

    /**
     * 奖品设置信息的mapper接口
     */
    @Resource
    public OpTreChestPrizeMapper opTreChestPrizeMapper;

    /**
     * 藏品信息的mapper接口
     */
    @Resource
    public DcNftInfoMapper dcNftInfoMapper;

    /**
     * 会员抽奖次数mapper接口
     */
    @Resource
    public OpMbDrawNumMapper opMbDrawNumMapper;

    /**
     * 藏品证书mapper接口
     */
    @Resource
    public DcNftCertMapper dcNftCertMapper;

    /**
     * 藏品抽奖记录mapper接口
     */
    @Resource
    public OpNftDrawLogMapper opNftDrawLogMapper;

    /**
     * 积分抽奖记录mapper接口
     */
    @Resource
    public OpInteDrawLogMapper opInteDrawLogMapper;

    /**
     * 藏品流转记录mapper接口
     */
    @Resource
    public DcFlowLogMapper dcFlowLogMapper;

    /**
     * 会员信息mapper接口
     */
    @Resource
    public IMbMemberMapper iMbMemberMapper;

    /**
     * 链操作日志接口
     */
    @Resource
    public ChainOptLogMapper chainOptLogMapper;

    /**
     * 上链的接口
     */
    @Resource
    public DevBlockChainApi devBlockChainApi;

    @Resource
    public IDcNftCertService iDcNftCertService;
    /**
     * 添加宝箱活动接口功能
     *
     * @param opTreChestBo 宝箱活动信息
     * @return Boolean true，成功/false，失败
     */
    @Override
    public Boolean addTreChest(OpTreChestInfoBo opTreChestBo) {
        log.info("开始添加宝箱活动:{" + opTreChestBo + "}");
        boolean add = false;
        //设置创建时间
        opTreChestBo.setCreateTime(new Date());
        //转为实体类
        OpTreChestInfo opTreChest = BeanUtil.toBean(opTreChestBo, OpTreChestInfo.class);
        //生成一个活动标识
        String id = IdUtil.getSnowflakeNextIdStr();
        //设置宝箱活动标识
        opTreChest.setId(id);

        //获取宝箱活动抽奖方式
        Integer drawMode = opTreChest.getDrawMode();
        //设置默认删除标识（0）
        opTreChest.setDeleteFlag(0);
        //藏品抽奖
        if (drawMode.equals(OpTCEnum.NFTDRAWLOG.getValue())) {
            //获取藏品抽奖消耗原材料信息
            List<OpNftTreChestBo> nftTreChestBos = opTreChestBo.getOpNftTreChestBos();
            if (nftTreChestBos.size() == OpTCEnum.ISNULL.getValue()) {
                log.error("藏品抽奖消耗为空");
                throw new CommonException("藏品抽奖消耗不能为空");
            }
            //转为实体类
            List<OpNftTreChest> opNftTreChests = BeanUtil.copyToList(nftTreChestBos, OpNftTreChest.class);
            //循环藏品抽奖消耗原材料信息
            for (OpNftTreChest opNftTreChest : opNftTreChests) {
                //设置宝箱活动的标识
                opNftTreChest.setTreChestId(id);
            }
            //添加藏品抽奖消耗原材料信息
            boolean b = opNftTreChestMapper.insertBatch(opNftTreChests);
            if (!b) {
                log.error("藏品抽奖消耗原材料添加失败");
                throw new CommonException("藏品抽奖消耗原材料添加失败");
            }
        }
        //获取宝箱奖品设置信息
        List<OpTreChestPrizeBo> treChestPrizeBos = opTreChestBo.getOpTreChestPrizeBos();
        if (treChestPrizeBos.size() == OpTCEnum.ISNULL.getValue()) {
            log.error("奖品设置信息为空");
            throw new CommonException("奖品不能为空");
        }
        //将宝箱奖品设置信息转为实体类
        List<OpTreChestPrize> opTreChestPrizes = BeanUtil.copyToList(treChestPrizeBos, OpTreChestPrize.class);
        for (OpTreChestPrize opTreChestPrize : opTreChestPrizes) {
            //获取奖品标识
            String nftId = opTreChestPrize.getNftId();
            //获取奖品数量
            Integer prizeQuaBack = opTreChestPrize.getPrizeQua();
            //根据奖品标识查出藏品的剩余库存
            QueryWrapper<DcNftInfo> dcNftInfoQueryWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<DcNftInfo> dcNftLambda = dcNftInfoQueryWrapper.lambda();
            dcNftLambda.eq(DcNftInfo::getId, nftId);
            DcNftInfo dcNftInfo = dcNftInfoMapper.selectOne(dcNftLambda);
            //获取剩余库存
            Integer inventory = dcNftInfo.getInventory();
            //获取该藏品的名称
            String name = dcNftInfo.getName();
            //根据奖品标识获取所有活动设置该奖品的信息
            Integer prize = 0;
            QueryWrapper<OpTreChestPrize> opTreChestPrizeQueryWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<OpTreChestPrize> opTreChestLambda = opTreChestPrizeQueryWrapper.lambda();
            opTreChestLambda.eq(OpTreChestPrize::getNftId, nftId);
            List<OpTreChestPrize> opTrePrizes = opTreChestPrizeMapper.selectList(opTreChestLambda);
            for (OpTreChestPrize treChest : opTrePrizes) {
                //获取奖品设置的剩余数量进行累计
                Integer prizeRemQua = treChest.getPrizeRemQua();
                prize = prize + prizeRemQua;
            }
            //使用该藏品的剩余库存减去所有设置的该奖品的数量
            Integer intInven = inventory - prize;
            //判断剩余的库存数量是否大于本次设置的奖品数量
            int compare = intInven.compareTo(prizeQuaBack);
            //剩余库存小于奖品设置的数量
            if (compare < 0) {
                log.error("藏品库存不足");
                //直接返回藏品库存不足
                throw new CommonException(OpTCEnum.NFTINVENTORY.getName() + "," + name + OpTCEnum.INVENTORY.getName() + inventory);
            }
            //设置宝箱奖品设置信息标识
            opTreChestPrize.setId(IdUtil.getSnowflakeNextIdStr());
            //设置宝箱奖品活动信息标识
            opTreChestPrize.setTreChestId(id);
            //设置宝箱奖品的剩余数量
            opTreChestPrize.setPrizeRemQua(prizeQuaBack);
        }
        //批量添加宝箱奖品设置信息
        boolean b = opTreChestPrizeMapper.insertBatch(opTreChestPrizes);
        //添加宝箱活动信息
        int insert = mapper.insert(opTreChest);
        if (b && insert > 0) {
            add = true;
        }
        log.info("添加宝箱活动完成");
        return add;
    }

    /**
     * 查询宝箱活动接口功能
     *
     * @param keyword  关键字
     * @param status   宝箱活动状态
     * @param pageNo   当前第几页
     * @param pageSize 每页显示条数
     * @return 分页信息
     */
    @Override
    public Page<OpTreChestInfoVo> queryTreChestByPage(String keyword, Integer status, Integer pageNo, Integer pageSize) {
        //当前第几页至少为第一页
        if (pageNo <= 0) {
            pageNo = 1;
        }
        //每页显示条数至少为1条
        if (pageSize <= 0) {
            pageSize = 1;
        }
        QueryWrapper<OpTreChestInfo> opTreChestInfoQueryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<OpTreChestInfo> lambda = opTreChestInfoQueryWrapper.lambda();
        if (!StringUtil.isEmpty(keyword) && !Objects.equals(keyword, "")) {
            lambda.like(OpTreChestInfo::getOpTitle, keyword);
        }
        if (status != null && !status.equals("")) {
            lambda.eq(OpTreChestInfo::getStatus, status);
        }
        lambda.orderByDesc(OpTreChestInfo::getCreateTime);
        //创建分页
        Page<OpTreChestInfo> page = new Page<>(pageNo, pageSize);
        Page<OpTreChestInfoVo> opTreChestInfoVoPage = mapper.selectVoPage(page, lambda);
        //获取活动信息
        List<OpTreChestInfoVo> records = opTreChestInfoVoPage.getRecords();
        if (records == null) {
            return opTreChestInfoVoPage;
        }
        //循环宝箱活动信息
        for (OpTreChestInfoVo opTreChestInfoVo : records) {
            //获取活动标识
            String id = opTreChestInfoVo.getId();
            //获取抽奖方式
            Integer drawMode = opTreChestInfoVo.getDrawMode();
            //抽奖方式为藏品抽奖
            if (drawMode.equals(OpTCEnum.NFTDRAWLOG.getValue())) {
                //根据活动标识获取藏品抽奖消耗原材料
                QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
                LambdaQueryWrapper<OpNftTreChest> opNftTreLambda = opNftTreChestQueryWrapper.lambda();
                opNftTreLambda.eq(OpNftTreChest::getTreChestId, id);
                //获取抽奖消耗原材料信息*
                List<OpNftTreChestVo> opNftTreChestVos = opNftTreChestMapper.selectVoList(opNftTreLambda);
                //TODO:添加为空判断
                //循环抽奖消耗原材料信息
                for (OpNftTreChestVo opNftTreChestVo : opNftTreChestVos) {
                    //获取藏品标识
                    String nftId = opNftTreChestVo.getNftId();
                    //根据藏品标识获取藏品信息
                    DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                    //获取藏品信息
                    opNftTreChestVo.setNftName(dcNftInfo.getName());
                    //获取藏品封面
                    opNftTreChestVo.setCover(dcNftInfo.getCover());
                }
                opTreChestInfoVo.setOpNftTreChestVos(opNftTreChestVos);
            }
            //查询宝箱奖品设置信息
            QueryWrapper<OpTreChestPrize> opTreChestPrizeWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<OpTreChestPrize> opTreChestPrizeLambda = opTreChestPrizeWrapper.lambda();
            opTreChestPrizeLambda.eq(OpTreChestPrize::getTreChestId, id);
            List<OpTreChestPrizeVo> opTreChestPrizeVos = opTreChestPrizeMapper.selectVoList(opTreChestPrizeLambda);
            if (ObjectUtil.isEmpty(opTreChestPrizeVos)) {
                throw new CommonException("奖品不能为空");
            }
            for (OpTreChestPrizeVo opTreChestPrizeVo : opTreChestPrizeVos) {
                //获取藏品标识
                String nftId = opTreChestPrizeVo.getNftId();
                //根据藏品标识获取藏品信息
                DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                //设置藏品信息
                opTreChestPrizeVo.setNftName(dcNftInfo.getName());
                //设置藏品封面
                opTreChestPrizeVo.setCover(dcNftInfo.getCover());
            }
            opTreChestInfoVo.setOpTreChestPrizeVos(opTreChestPrizeVos);
        }
        return opTreChestInfoVoPage;
    }

    /**
     * 启用宝箱活动信息
     *
     * @param id 宝箱活动信息标识
     * @return Boolean true，成功/false，失败
     */
    @Override
    public Boolean startTreChest(String id) {
        UpdateWrapper<OpTreChestInfo> opTreChestInfoUpdateWrapper = new UpdateWrapper<>();
        opTreChestInfoUpdateWrapper.lambda().set(OpTreChestInfo::getStatus, OpTCEnum.START.getValue()).eq(OpTreChestInfo::getId, id);
        int update = mapper.update(null, opTreChestInfoUpdateWrapper);
        return update > 0;
    }

    /**
     * 停用宝箱活动信息
     *
     * @param id 宝箱活动信息标识
     * @return Boolean true，成功/false，失败
     */
    @Override
    public Boolean stopTreChest(String id) {
        UpdateWrapper<OpTreChestInfo> opTreChestInfoUpdateWrapper = new UpdateWrapper<>();
        opTreChestInfoUpdateWrapper.lambda().set(OpTreChestInfo::getStatus, OpTCEnum.STOP.getValue()).eq(OpTreChestInfo::getId, id);
        int update = mapper.update(null, opTreChestInfoUpdateWrapper);
        return update > 0;
    }

    /**
     * 查看宝箱活动信息
     *
     * @param id 宝箱活动标识
     * @return 宝箱活动信息
     */
    @Override
    public OpTreChestInfoVo getTreChest(String id) {
        //查出宝箱活动信息
        OpTreChestInfoVo opTreChestInfoVo = mapper.selectVoById(id);
        //不为空
        if (!ObjectUtil.isEmpty(opTreChestInfoVo)) {
            //藏品抽奖
            if (opTreChestInfoVo.getDrawMode().equals(OpTCEnum.NFTDRAWLOG.getValue())) {
                QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
                LambdaQueryWrapper<OpNftTreChest> opNftTreLambda = opNftTreChestQueryWrapper.lambda();
                opNftTreLambda.eq(OpNftTreChest::getTreChestId, id);
                //获取抽奖消耗原材料信息*
                List<OpNftTreChestVo> opNftTreChestVos = opNftTreChestMapper.selectVoList(opNftTreLambda);
                opTreChestInfoVo.setOpNftTreChestVos(opNftTreChestVos);
                //循环抽奖消耗原材料信息
                for (OpNftTreChestVo opNftTreChestVo : opNftTreChestVos) {
                    //获取藏品标识
                    String nftId = opNftTreChestVo.getNftId();
                    //根据藏品标识获取藏品信息
                    DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                    //获取藏品信息
                    opNftTreChestVo.setNftName(dcNftInfo.getName());
                    //获取藏品封面
                    opNftTreChestVo.setCover(dcNftInfo.getCover());
                }
            }
            //获取奖品设置信息
            QueryWrapper<OpTreChestPrize> opTreChestPrizeWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<OpTreChestPrize> opTreChestPrizeLambda = opTreChestPrizeWrapper.lambda();
            opTreChestPrizeLambda.eq(OpTreChestPrize::getTreChestId, id);
            List<OpTreChestPrizeVo> opTreChestPrizeVos = opTreChestPrizeMapper.selectVoList(opTreChestPrizeLambda);
            for (OpTreChestPrizeVo opTreChestPrizeVo : opTreChestPrizeVos) {
                //获取藏品标识
                String nftId = opTreChestPrizeVo.getNftId();
                //根据藏品标识获取藏品信息
                DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                //设置藏品信息
                opTreChestPrizeVo.setNftName(dcNftInfo.getName());
                //设置藏品封面
                opTreChestPrizeVo.setCover(dcNftInfo.getCover());
                //获取藏品的发行数量
                opTreChestPrizeVo.setPublisnum(String.valueOf(dcNftInfo.getPublishNum()));
            }
            opTreChestInfoVo.setOpTreChestPrizeVos(opTreChestPrizeVos);
        }
        return opTreChestInfoVo;
    }

    /**
     * 删除宝箱活动信息
     *
     * @param id 宝箱活动信息标识
     * @return Boolean true，成功/false，失败
     */
    @Override
    public Boolean delTreChest(String id) {
        //查出此条宝箱活动信息
        OpTreChestInfo opTreChestInfo = mapper.selectById(id);
        if (opTreChestInfo.getDeleteFlag().equals(OpTCEnum.DELETEFLAG.getValue())) {
            return true;
        }
        opTreChestInfo.setDeleteFlag(OpTCEnum.DELETEFLAG.getValue());
        //更新这条宝箱活动信息
        int i = mapper.updateById(opTreChestInfo);
        return i > 0;
    }

    /**
     * 编辑宝箱活动信息
     *
     * @param opTreChestInfoBo 宝箱活动信息
     * @return Boolean true，成功/false，失败
     */
    @Override
    public Boolean updateTreChest(OpTreChestInfoBo opTreChestInfoBo) {
        boolean update = false;
        //更新时间
        opTreChestInfoBo.setUpdateTime(new Date());
        //转为实体类
        OpTreChestInfo opTreChestInfo = BeanUtil.toBean(opTreChestInfoBo, OpTreChestInfo.class);
        //获取宝箱活动标识
        String id = opTreChestInfo.getId();
        //获取活动抽取方式
        Integer drawMode = opTreChestInfo.getDrawMode();
        //抽奖方式为积分抽奖
        if (drawMode.equals(OpTCEnum.INTEDRAWLOG.getValue())) {
            QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<OpNftTreChest> opNftTreChestLambda = opNftTreChestQueryWrapper.lambda();
            opNftTreChestLambda.eq(OpNftTreChest::getTreChestId, id);
            //调用删除抽奖消耗原材料的mapper接口
            opNftTreChestMapper.delete(opNftTreChestLambda);
        }
        //抽奖方式为藏品抽奖
        if (drawMode.equals(OpTCEnum.NFTDRAWLOG.getValue())) {
            //调用清空该活动消耗积分字段的mapper接口
            OpTreChestInfo opTreChest = mapper.selectById(id);
            opTreChest.setConInte(null);
            mapper.updateById(opTreChestInfo);
            QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
            LambdaQueryWrapper<OpNftTreChest> opNftTreChestLambda = opNftTreChestQueryWrapper.lambda();
            opNftTreChestLambda.eq(OpNftTreChest::getTreChestId, id);
            //删除原来设置的抽奖消耗原材料信息
            opNftTreChestMapper.delete(opNftTreChestLambda);
            //重新添加设置的抽奖消耗原材料信息
            List<OpNftTreChestBo> opNftTreChestBos = opTreChestInfoBo.getOpNftTreChestBos();
            List<OpNftTreChest> opNftTreChests = BeanUtil.copyToList(opNftTreChestBos, OpNftTreChest.class);
            opNftTreChestMapper.insertBatch(opNftTreChests);
        }
        //删除宝箱奖品设置信息
        QueryWrapper<OpTreChestPrize> opTreChestPrizeQueryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<OpTreChestPrize> opTreChestPrizeLambda = opTreChestPrizeQueryWrapper.lambda();
        opTreChestPrizeLambda.eq(OpTreChestPrize::getTreChestId, id);
        opTreChestPrizeMapper.delete(opTreChestPrizeLambda);
        //获取重新选择奖品设置信息
        List<OpTreChestPrizeBo> opTreChestPrizeBos = opTreChestInfoBo.getOpTreChestPrizeBos();
        List<OpTreChestPrize> opTreChestPrizes = BeanUtil.copyToList(opTreChestPrizeBos, OpTreChestPrize.class);
        for (OpTreChestPrize opTreChestPrize : opTreChestPrizes) {
            //获取奖品标识
            String nftId = opTreChestPrize.getNftId();
            //获取奖品数量
            Integer prizeQua = opTreChestPrize.getPrizeQua();
            //根据奖品标识查出该奖品的剩余库存
            DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
            //获取该藏品的剩余库存
            Integer inventory = dcNftInfo.getInventory();
            //获取该藏品的名称
            String name = dcNftInfo.getName();
            Integer prize = 0;
            //查出所有设置该藏品为奖品的信息
            QueryWrapper<OpTreChestPrize> opTreChestPrizeQueryWrapper1 = new QueryWrapper<>();
            LambdaQueryWrapper<OpTreChestPrize> opTreChestLambda = opTreChestPrizeQueryWrapper1.lambda();
            opTreChestLambda.eq(OpTreChestPrize::getNftId, nftId);
            List<OpTreChestPrize> opTrePrizes = opTreChestPrizeMapper.selectList(opTreChestLambda);
            for (OpTreChestPrize treChest : opTrePrizes) {
                //获取奖品设置的剩余数量进行累计
                Integer prizeRemQua = treChest.getPrizeRemQua();
                prize = prize + prizeRemQua;
            }
            //使用该藏品的剩余库存减去所有设置的该奖品的数量
            Integer intInven = inventory - prize;
            //判断剩余的库存数量是否大于本次设置的奖品数量
            int compare = intInven.compareTo(prizeQua);
            //剩余库存小于奖品设置的数量
            if (compare < 0) {
                //直接返回藏品库存不足
                throw new CommonException(OpTCEnum.NFTINVENTORY.getName() + "," + name + OpTCEnum.INVENTORY.getName() + inventory);
            }
            //设置宝箱奖品设置信息标识
            opTreChestPrize.setId(IdUtil.getSnowflakeNextIdStr());
            //设置宝箱奖品活动信息标识
            opTreChestPrize.setTreChestId(id);
            //设置宝箱奖品的剩余数量
            opTreChestPrize.setPrizeRemQua(prizeQua);
        }
        //批量插入奖品设置信息
        boolean b = opTreChestPrizeMapper.insertBatch(opTreChestPrizes);
        //编辑宝箱活动信息mapper接口
        int insert = mapper.updateById(opTreChestInfo);
        if (b && insert > 0) {
            update = true;
        }
        return update;
    }

    /**
     * 积分抽奖
     *
     * @param mbId  会员标识
     * @param treId 宝箱活动标识
     * @return 藏品信息
     */
    @Override
    public DcNftCertVo inteTreChest(String mbId, String treId) {

        OpTreChestInfoVo treChest = getTreChest(treId);
        Date opStartTime = treChest.getOpStartTime();
        Date opEndTime = treChest.getOpEndTime();
        Date date = new Date();
        //判断当前时间是否大于开始时间
        if (opStartTime.after(date)) {
            throw new CommonException("当前活动未开始，请稍后重试");
        } else if (opEndTime.before(date)) {
            throw new CommonException("当前活动已结束，请期待下次活动");
        }

        DcNftCertVo dcNftCertVo = new DcNftCertVo();
        //查询抽奖次数
        OpTreChestInfo opTreChestInfo = mapper.selectById(treId);
        //查询活动抽奖次数
        Integer drawChaNum = opTreChestInfo.getDrawChaNum();
        //消耗积分
        Integer inte = opTreChestInfo.getConInte();
        //查看会员的剩余抽奖次数
        QueryWrapper<OpMbDrawNum> opMbDrawNumQueryWrapper = new QueryWrapper<>();
        opMbDrawNumQueryWrapper.lambda().eq(OpMbDrawNum::getMbId, mbId).eq(OpMbDrawNum::getTreChestId, treId);
        OpMbDrawNum opMbDrawNum = opMbDrawNumMapper.selectOne(opMbDrawNumQueryWrapper);
        if (opMbDrawNum != null) {
            //获取剩余抽奖次数
            Integer remDraw = opMbDrawNum.getRemDraw();
            //剩余抽奖次数是否为0
            if (remDraw.equals(OpTCEnum.ZERO.getValue())) {
                //为0则直接返回没有抽奖次数了
                throw new CommonException(OpTCEnum.DRAWNUM.getName());
            }
            //----------根据会员标识和宝箱活动标识去修改该会员在此次活动中的剩余抽奖次数----------//
            //剩余抽奖次数
            remDraw = remDraw - OpTCEnum.NUM.getValue();
            //调用修改会员在此次活动中的剩余抽奖次数mapper接口
            UpdateWrapper<OpMbDrawNum> opMbDrawNumUpdateWrapper = new UpdateWrapper<>();
            LambdaUpdateWrapper<OpMbDrawNum> lambda = opMbDrawNumUpdateWrapper.lambda();
            lambda.set(OpMbDrawNum::getRemDraw, remDraw).eq(OpMbDrawNum::getMbId, mbId).eq(OpMbDrawNum::getTreChestId, treId);
            opMbDrawNumMapper.update(null, lambda);
        }
        //判断在此次活动中是否为首次抽奖
        if (ObjectUtil.isEmpty(opMbDrawNum)) {
            //使用雪花算法产生一个新的会员抽奖次数信息标识
            String snoIdStr = IdUtil.getSnowflakeNextIdStr();
            OpMbDrawNum opMbDrawNumNew = new OpMbDrawNum();
            //为首次抽奖则在会员抽奖信息表中添加信息
            opMbDrawNumNew.setId(snoIdStr);
            //会员标识
            opMbDrawNumNew.setMbId(mbId);
            //活动标识
            opMbDrawNumNew.setTreChestId(treId);
            //剩余抽奖次数
            opMbDrawNumNew.setRemDraw(drawChaNum);
            //添加会员抽奖信息
            int insert = opMbDrawNumMapper.insert(opMbDrawNumNew);
            if (insert <= 0) {
                log.error("添加会员抽奖信息失败");
                throw new CommonException("添加会员抽奖信息失败");
            }
        }
        //查看会员积分信息
        MbUserInfo mbUserInfo = iMbMemberMapper.selectById(mbId);
        //获取会员积分余额
        Integer instInteBal = mbUserInfo.getInstInteBal();
        //查出的会员积分余额和所需消耗积分对比
        int i1 = instInteBal.compareTo(inte);
        //如果剩余积分小于此次活动抽奖所消耗的积分
        if (i1 < 0) {
            //直接返回积分不足
            throw new CommonException(OpTCEnum.INSTINTEBAL.getName());
        }
        //扣除会员用于抽奖消耗积分
        Integer in = instInteBal - inte;
        //修改会员积分余额
        UpdateWrapper<MbUserInfo> mbUserInfoUpdateWrapper = new UpdateWrapper<>();
        mbUserInfoUpdateWrapper.lambda().set(MbUserInfo::getInstInteBal, in).eq(MbUserInfo::getId, mbId);
        iMbMemberMapper.update(null, mbUserInfoUpdateWrapper);
        //获取一个随机数
        Random random = new Random();
        int i = random.nextInt(100);
        //获取该活动的宝箱奖品设置信息
        QueryWrapper<OpTreChestPrize> opTreChestPrizeQueryWrapper = new QueryWrapper<>();
        opTreChestPrizeQueryWrapper.lambda().eq(OpTreChestPrize::getTreChestId, treId);
        List<OpTreChestPrize> opTreChestPrizes = opTreChestPrizeMapper.selectList(opTreChestPrizeQueryWrapper);
        //创建一个累加器
        int accumulator = 0;
        for (OpTreChestPrize opTreChestPrize : opTreChestPrizes) {
            //获取此奖品设置信息的标识
            String id = opTreChestPrize.getId();
            //获取宝箱奖品设置信息中的奖品概率
            Integer parizeCha = opTreChestPrize.getPrizeCha();
            //获取奖品标识
            String nftId = opTreChestPrize.getNftId();
            accumulator += parizeCha;
            if (i <= accumulator) {
                //查询此奖品的的剩余数量
                Integer prizeRemQua = opTreChestPrize.getPrizeRemQua();
                //如果抽中的奖品剩余数量为0
                if (prizeRemQua.equals(OpTCEnum.RESNFTNUM.getValue())) {
                    //生成藏品抽奖记录
                    OpNftDrawLog nftDrawLog = new OpNftDrawLog();
                    //使用雪花算法产生一个新的藏品流转记录标识
                    String nftDrawLogId = IdUtil.getSnowflakeNextIdStr();
                    //藏品抽奖记录标识
                    nftDrawLog.setId(nftDrawLogId);
                    //会员标识
                    nftDrawLog.setMbId(mbId);
                    //奖品标识
                    nftDrawLog.setPrizeId(null);
                    //藏品证书标识
                    nftDrawLog.setNftCerId(null);
                    //宝箱活动的标识
                    nftDrawLog.setTreChestId(treId);
                    //抽奖时间
                    nftDrawLog.setNftDrawTime(new Date());
                    //调用添加藏品抽奖记录信息的mapper接口
                    opNftDrawLogMapper.insert(nftDrawLog);
                    //返回没有抽中奖品
                    throw new CommonException(OpTCEnum.NODRAW.getName());
                }
                //将奖品库存减去1
                Integer prq = prizeRemQua - OpTCEnum.NUM.getValue();
                //修改该奖品设置信息的库存数量
                UpdateWrapper<OpTreChestPrize> opTreChestPrizeUpdateWrapper = new UpdateWrapper<>();
                opTreChestPrizeUpdateWrapper.lambda().set(OpTreChestPrize::getPrizeRemQua, prq).eq(OpTreChestPrize::getId, id);
                opTreChestPrizeMapper.update(null, opTreChestPrizeUpdateWrapper);

                //根据藏品标识查出该藏品的库存
                DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                //抽中的此类奖品减去1
                Integer inventory = dcNftInfo.getInventory() - OpTCEnum.NUM.getValue();
                //修改该藏品的库存
                UpdateWrapper<DcNftInfo> dcNftInfoUpdateWrapper = new UpdateWrapper<>();
                dcNftInfoUpdateWrapper.lambda().set(DcNftInfo::getInventory, inventory).eq(DcNftInfo::getId, nftId);
                dcNftInfoMapper.update(null, dcNftInfoUpdateWrapper);

                //上链
                DcNftCert dcNftCert = iDcNftCertService.genCert(nftId, mbId, ChainLogEnum.BUSINESS_DRAW.getValue());
                //持有人标识
                dcNftCert.setMbId(mbId);
                //添加藏品证书信息
                dcNftCertMapper.insert(dcNftCert);
                //将Bo转为Vo
                dcNftCertVo = BeanUtil.toBean(dcNftCert, DcNftCertVo.class);
                //封装藏品名称
                dcNftCertVo.setNftName(dcNftInfo.getName());
                //封装藏品封面
                dcNftCertVo.setNftCover(dcNftInfo.getCover());

                //生成藏品流转记录
                DcFlowLog dcFlowLog = new DcFlowLog();
                //使用雪花算法产生一个新的藏品流转记录标识
                String dcFlowLogId = IdUtil.getSnowflakeNextIdStr();
                //流转记录标识
                dcFlowLog.setId(dcFlowLogId);
                //藏品证书标识
                dcFlowLog.setCertId(dcNftCert.getId());
                //流转方式
                dcFlowLog.setCirculation(OpTCEnum.DCFLOWDRAW.getValue());
                //流转时间
                dcFlowLog.setFlowTime(new Date());
                //调用添加藏品流转记录mapper接口
                dcFlowLogMapper.insert(dcFlowLog);
                //生成积分抽奖记录
                OpInteDrawLog opInteDrawLog = new OpInteDrawLog();
                //使用雪花算法产生一个新的藏品流转记录标识
                String nftDrawLogId = IdUtil.getSnowflakeNextIdStr();
                //藏品抽奖记录标识
                opInteDrawLog.setId(nftDrawLogId);
                //会员标识
                opInteDrawLog.setMbId(mbId);
                //奖品标识
                opInteDrawLog.setPrizeId(nftId);
                //藏品证书标识
                opInteDrawLog.setNftCertId(dcNftCert.getId());
                //宝箱活动的标识
                opInteDrawLog.setTreChestId(treId);
                //抽奖时间
                opInteDrawLog.setInteDrawTime(new Date());
                //添加藏品抽奖记录信息
                opInteDrawLogMapper.insert(opInteDrawLog);
                //本次抽奖消耗的积分
                opInteDrawLog.setInteExp(inte);
                break;
            }
        }
        if (i > accumulator) {
            //生成积分抽奖记录信息
            OpInteDrawLog opInteDrawLog = new OpInteDrawLog();
            //使用雪花算法产生一个新的藏品流转记录标识
            String opInteDrawLogId = IdUtil.getSnowflakeNextIdStr();
            //积分抽奖记录标识
            opInteDrawLog.setId(opInteDrawLogId);
            //会员标识
            opInteDrawLog.setMbId(mbId);
            //奖品标识
            opInteDrawLog.setPrizeId(null);
            //宝箱活动标识
            opInteDrawLog.setTreChestId(treId);
            //藏品证书标识
            opInteDrawLog.setNftCertId(null);
            //抽奖时间
            opInteDrawLog.setInteDrawTime(new Date());
            //添加藏品抽奖记录信息
            opInteDrawLogMapper.insert(opInteDrawLog);
            throw new CommonException(OpTCEnum.NODRAW.getName());
        }
        return dcNftCertVo;
    }

    /**
     * 藏品抽奖
     *
     * @param dcNftCertBos 藏品证书信息*
     * @param mbId         会员标识
     * @param treId        宝箱活动标识
     * @return 藏品证书标识
     */
    @Override
    public DcNftCertVo nftTreChest(List<DcNftCertBo> dcNftCertBos, String mbId, String treId) {

        OpTreChestInfoVo treChest = getTreChest(treId);
        Date opStartTime = treChest.getOpStartTime();
        Date opEndTime = treChest.getOpEndTime();
        Date date = new Date();
        //判断当前时间是否大于开始时间
        if (opStartTime.after(date)) {
            throw new CommonException("当前活动未开始，请稍后重试");
        } else if (opEndTime.before(date)) {
            throw new CommonException("当前活动已结束，请期待下次活动");
        }

        //查看会员信息
        MbUserInfo mbUserInfo = iMbMemberMapper.selectById(mbId);
        //获取会员链上地址
        String owner = mbUserInfo.getNativeAddress();

        DcNftCertVo dcNftCertVo = new DcNftCertVo();
        //获取宝箱活动
        OpTreChestInfo opTreChestInfo = mapper.selectById(treId);
        //获取活动抽奖次数
        Integer drawChaNum = opTreChestInfo.getDrawChaNum();
        //查看会员的剩余抽奖次数
        QueryWrapper<OpMbDrawNum> opMbDrawNumQueryWrapper = new QueryWrapper<>();
        opMbDrawNumQueryWrapper.lambda().eq(OpMbDrawNum::getMbId, mbId).eq(OpMbDrawNum::getTreChestId, treId);
        OpMbDrawNum opMbDrawNum = opMbDrawNumMapper.selectOne(opMbDrawNumQueryWrapper);
        //信息不为空(不是首次抽奖)
        if (!ObjectUtil.isEmpty(opMbDrawNum)) {
            //获取剩余抽奖次数
            Integer remDraw = opMbDrawNum.getRemDraw();
            //剩余抽奖次数是否为0
            if (remDraw.equals(OpTCEnum.ZERO.getValue())) {
                //为0则直接返回没有抽奖次数了
                throw new CommonException(OpTCEnum.DRAWNUM.getName());
            }
            //----------根据会员标识和宝箱活动标识去修改该会员在此次活动中的剩余抽奖次数----------
            //剩余抽奖次数
            remDraw = remDraw - OpTCEnum.NUM.getValue();
            //调用修改会员在此次活动中的剩余抽奖次数mapper接口
            UpdateWrapper<OpMbDrawNum> opMbDrawNumUpdateWrapper = new UpdateWrapper<>();
            LambdaUpdateWrapper<OpMbDrawNum> lambda = opMbDrawNumUpdateWrapper.lambda();
            lambda.set(OpMbDrawNum::getRemDraw, remDraw).eq(OpMbDrawNum::getMbId, mbId).eq(OpMbDrawNum::getTreChestId, treId);
            opMbDrawNumMapper.update(null, lambda);
        }
        //判断在此次活动中是否为首次抽奖
        if (ObjectUtil.isEmpty(opMbDrawNum)) {
            OpMbDrawNum opMbDrawNum1 = new OpMbDrawNum();
            //使用雪花算法产生一个新的会员抽奖次数信息标识
            String snoIdStr = IdUtil.getSnowflakeNextIdStr();
            //为首次抽奖则在会员抽奖信息表中添加信息
            opMbDrawNum1.setId(snoIdStr);
            //会员标识
            opMbDrawNum1.setMbId(mbId);
            //活动标识
            opMbDrawNum1.setTreChestId(treId);
            //剩余抽奖次数
            opMbDrawNum1.setRemDraw(drawChaNum);
            //添加会员抽奖信息
            int insert = opMbDrawNumMapper.insert(opMbDrawNum1);
            if (insert <= 0) {
                log.error("添加会员抽奖信息失败");
                throw new CommonException("添加会员抽奖信息失败");
            }
        }
        //使用宝箱活动id获取抽奖消耗原材料料信息
        QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
        opNftTreChestQueryWrapper.lambda().eq(OpNftTreChest::getTreChestId, treId);
        List<OpNftTreChestVo> opNftTreChestVos = opNftTreChestMapper.selectVoList(opNftTreChestQueryWrapper);
        String nftId = "";
        Integer nftExpQua = null;
        for (OpNftTreChestVo opNftTreChestVo : opNftTreChestVos) {
            //取出藏品标识和藏品消耗数量
            nftId = opNftTreChestVo.getNftId();
            nftExpQua = opNftTreChestVo.getNftExpQua();
        }
        //获取会员拥有的所有此藏品数据
        QueryWrapper<DcNftCert> dcNtfCertQueryWrapper = new QueryWrapper<>();
        dcNtfCertQueryWrapper.lambda().eq(DcNftCert::getMbId, mbId).eq(DcNftCert::getNftId, nftId).eq(DcNftCert::getStatus, OpTCEnum.POSSESS.getValue());
        List<DcNftCertVo> dcNftCertVos = dcNftCertMapper.selectVoList(dcNtfCertQueryWrapper);
        Integer integer = dcNftCertVos.size();
        //如果总条数为0，返回不满足抽奖条件
        if (integer.equals(OpTCEnum.ZERO.getValue())) {
            //不满足抽奖条件
            log.error(OpTCEnum.NFTINSUFFICIENT.getName());
            throw new CommonException(OpTCEnum.NFTINSUFFICIENT.getName());
        }
        //拥有的此藏品数量是否满足抽奖条件
        int i = integer.compareTo(nftExpQua);
        if (i < 0) {
            //不满足抽奖条件
            log.error(OpTCEnum.NFTINSUFFICIENT.getName());
            throw new CommonException(OpTCEnum.NFTINSUFFICIENT.getName());
        }
        //循环取出藏品证书信息
        for (DcNftCertBo dcNftCertBo : dcNftCertBos) {
            //转为实体类
            DcNftCert dcNftCert = BeanUtil.toBean(dcNftCertBo, DcNftCert.class);
            //获取藏品证书标识
            String id = dcNftCert.getId();
            //根据会员标识和藏品证书标识去修改该会员消耗的藏品证书状态为销毁状态
            UpdateWrapper<DcNftCert> dcNtfCertUpdateWrapper = new UpdateWrapper<>();
            LambdaUpdateWrapper<DcNftCert> lambda = dcNtfCertUpdateWrapper.lambda();
            lambda.set(DcNftCert::getStatus, OpTCEnum.NFTCERTSTATUS.getValue()).eq(DcNftCert::getId, id).eq(DcNftCert::getMbId, mbId);
            dcNftCertMapper.update(null, lambda);
//            String operationId = devBlockChainApi.disNft(dcNftCert.getChainAddr(), owner, dcNftCert.getNftId());
//            //根据操作id调用查询链交易记录
//            TradingResultsInfo tradingResultsInfo = devBlockChainApi.queryTranRecords(operationId);
//            TradingResultsInfo.Data data = tradingResultsInfo.getData();
//            //获取操作状态
//            Integer status = data.getStatus();
//            //封装链操作日志信息
//            ChainOptLogInfo chainOptLogInfo = new ChainOptLogInfo();
//            String logId = IdUtil.getSnowflakeNextIdStr();
//            //链操作日志标识
//            chainOptLogInfo.setId(logId);
//            //平台操作类型
//            chainOptLogInfo.setDcOptType(null);
//            //文昌链操作类型
//            chainOptLogInfo.setChainOptType(ChainLogEnum.CHAIN_DESTROYED_NFT.getValue());
//            //操作对象的id
//            chainOptLogInfo.setObjId(id);
//            //链上交易id
//            chainOptLogInfo.setOperationId(operationId);
//            //上链状态
//            chainOptLogInfo.setStatus(status);
//            //操作时间
//            chainOptLogInfo.setOptTime(new Date());
//            //操作描述
//            String destroyed = LogDescription.destroyed(mbId, id);
//            chainOptLogInfo.setOptDesc(destroyed);
//            //用户id
//            chainOptLogInfo.setUserId(mbId);
//            chainOptLogMapper.insert(chainOptLogInfo);
        }
        //获取一个随机数
        Random random = new Random();
        int randomVal = random.nextInt(100);
        //获取该活动的宝箱奖品设置信息
        QueryWrapper<OpTreChestPrize> opTreChestPrizeQueryWrapper = new QueryWrapper<>();
        opTreChestPrizeQueryWrapper.lambda().eq(OpTreChestPrize::getTreChestId, treId);
        List<OpTreChestPrize> opTreChestPrizes = opTreChestPrizeMapper.selectList(opTreChestPrizeQueryWrapper);
        //创建一个累加器
        int accumulator = 0;
        for (OpTreChestPrize opTreChestPrize : opTreChestPrizes) {
            //获取此奖品设置信息的标识
            String id = opTreChestPrize.getId();
            //获取宝箱奖品设置信息中的奖品概率
            Integer parizeCha = opTreChestPrize.getPrizeCha();
            //获取奖品标识
            String nftIdPrize = opTreChestPrize.getNftId();
            //概率累加
            accumulator += parizeCha;
            //判断生成的随机数在哪个藏品的概率之间
            if (randomVal <= accumulator) {
                //查询此奖品的的剩余数量
                Integer prizeRemQua = opTreChestPrize.getPrizeRemQua();
                //奖品数量为0
                if (prizeRemQua.equals(OpTCEnum.ZERO.getValue())) {
                    //生成藏品抽奖记录
                    OpNftDrawLog nftDrawLog = new OpNftDrawLog();
                    //使用雪花算法产生一个新的藏品流转记录标识
                    String nftDrawLogId = IdUtil.getSnowflakeNextIdStr();
                    //藏品抽奖记录标识
                    nftDrawLog.setId(nftDrawLogId);
                    //会员标识
                    nftDrawLog.setMbId(mbId);
                    //奖品标识
                    nftDrawLog.setPrizeId(null);
                    //藏品证书标识
                    nftDrawLog.setNftCerId(null);
                    //宝箱活动的标识
                    nftDrawLog.setTreChestId(treId);
                    //抽奖时间
                    nftDrawLog.setNftDrawTime(new Date());
                    //调用添加藏品抽奖记录信息的mapper接口
                    opNftDrawLogMapper.insert(nftDrawLog);
                    //返回没有抽中奖品
                    throw new CommonException(OpTCEnum.NODRAW.getName());
                }
                //将奖品库存减去1
                Integer prq = prizeRemQua - OpTCEnum.NUM.getValue();
                //修改该奖品设置信息的库存数量
                UpdateWrapper<OpTreChestPrize> opTreChestPrizeUpdateWrapper = new UpdateWrapper<>();
                opTreChestPrizeUpdateWrapper.lambda().set(OpTreChestPrize::getPrizeRemQua, prq).eq(OpTreChestPrize::getId, id);
                opTreChestPrizeMapper.update(null, opTreChestPrizeUpdateWrapper);
                //根据藏品标识查出该藏品的库存
                DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftIdPrize);
                //抽中的此类奖品减去1
                Integer inventory = dcNftInfo.getInventory() - OpTCEnum.NUM.getValue();
                //修改该藏品的库存
                UpdateWrapper<DcNftInfo> dcNftInfoUpdateWrapper = new UpdateWrapper<>();
                dcNftInfoUpdateWrapper.lambda().set(DcNftInfo::getInventory, inventory).eq(DcNftInfo::getId, nftIdPrize);
                dcNftInfoMapper.update(null, dcNftInfoUpdateWrapper);
                //上链
                DcNftCert dcNftCert = iDcNftCertService.genCert(nftId, mbId, ChainLogEnum.BUSINESS_DRAW.getValue());
                //持有人标识
                dcNftCert.setMbId(mbId);
                //添加藏品证书信息
                dcNftCertMapper.insert(dcNftCert);
                //将Bo转为Vo
                dcNftCertVo = BeanUtil.toBean(dcNftCert, DcNftCertVo.class);
                //封装藏品名称
                dcNftCertVo.setNftName(dcNftInfo.getName());
                //封装藏品封面
                dcNftCertVo.setNftCover(dcNftInfo.getCover());
                //生成藏品流转记录
                DcFlowLog dcFlowLog = new DcFlowLog();
                //使用雪花算法产生一个新的藏品流转记录标识
                String dcFlowLogId = IdUtil.getSnowflakeNextIdStr();
                //流转记录标识
                dcFlowLog.setId(dcFlowLogId);
                //藏品证书标识
                dcFlowLog.setCertId(dcNftCert.getId());
                //流转方式
                dcFlowLog.setCirculation(OpTCEnum.DCFLOWDRAW.getValue());
                //流转时间
                dcFlowLog.setFlowTime(new Date());
                //调用添加藏品流转记录mapper接口
                dcFlowLogMapper.insert(dcFlowLog);
                //生成藏品抽奖记录
                OpNftDrawLog opNftDrawLog = new OpNftDrawLog();
                //使用雪花算法产生一个新的藏品流转记录标识
                String nftDrawLogId = IdUtil.getSnowflakeNextIdStr();
                //藏品抽奖记录标识
                opNftDrawLog.setId(nftDrawLogId);
                //会员标识
                opNftDrawLog.setMbId(mbId);
                //奖品标识
                opNftDrawLog.setPrizeId(nftIdPrize);
                //藏品证书标识
                opNftDrawLog.setNftCerId(dcNftCert.getId());
                //宝箱活动的标识
                opNftDrawLog.setTreChestId(treId);
                //抽奖时间
                opNftDrawLog.setNftDrawTime(new Date());
                //调用添加藏品抽奖记录信息的mapper接口
                opNftDrawLogMapper.insert(opNftDrawLog);
                break;
            }
        }
        if (randomVal > accumulator) {
            //生成藏品抽奖记录
            OpNftDrawLog opNftDrawLog = new OpNftDrawLog();
            //使用雪花算法产生一个新的藏品流转记录标识
            String nftDrawLogId = IdUtil.getSnowflakeNextIdStr();
            //藏品抽奖记录标识
            opNftDrawLog.setId(nftDrawLogId);
            //会员标识
            opNftDrawLog.setMbId(mbId);
            //奖品标识
            opNftDrawLog.setPrizeId(null);
            //藏品证书标识
            opNftDrawLog.setNftCerId(null);
            //宝箱活动的标识
            opNftDrawLog.setTreChestId(treId);
            //抽奖时间
            opNftDrawLog.setNftDrawTime(new Date());
            //调用添加藏品抽奖记录信息的mapper接口
            opNftDrawLogMapper.insert(opNftDrawLog);
            //返回没有抽中奖品
            throw new CommonException(OpTCEnum.NODRAW.getName());
        }
        return dcNftCertVo;
    }

    /**
     * 查询宝箱抽奖记录功能接口
     *
     * @param treId 宝箱活动标识
     * @param mbId  会员标识
     * @return List<TreChestLogVo> 抽奖记录模型类
     */
    @Override
    public List<OpTreChestLogVo> getTreChestLog(String treId, String mbId) {

        List<OpTreChestLogVo> opTreChestLogVos = new ArrayList<>();
        //根据宝箱活动标识获取宝箱活动抽奖方式
        OpTreChestInfo opTreChestInfo = mapper.selectById(treId);
        //抽奖方式
        Integer drawMode = opTreChestInfo.getDrawMode();
        //根据抽奖方式获取其中一种抽奖记录
        //积分抽奖记录
        if (drawMode.equals(OpTCEnum.INTEDRAWLOG.getValue())) {
            //根据活动标识和会员标识查询积分抽奖记录
            QueryWrapper<OpInteDrawLog> opInteDrawLogQueryWrapper = new QueryWrapper<>();
            opInteDrawLogQueryWrapper.lambda().eq(OpInteDrawLog::getTreChestId, treId).eq(OpInteDrawLog::getMbId, mbId);
            List<OpInteDrawLogVo> opInteDrawLogVos = opInteDrawLogMapper.selectVoList(opInteDrawLogQueryWrapper);
            for (OpInteDrawLogVo treChestLogVo : opInteDrawLogVos) {
                OpTreChestLogVo opTreChestLogVo = new OpTreChestLogVo();
                //获取奖品标识
                String prizeId = treChestLogVo.getPrizeId();
                if (prizeId != null) {
                    //根据奖品标识查出奖品的信息
                    DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(prizeId);
                    opTreChestLogVo.setPrizeName(dcNftInfo.getName());
                    opTreChestLogVo.setCover(dcNftInfo.getCover());
                    opTreChestLogVo.setInteExp(treChestLogVo.getInteExp());
                    opTreChestLogVo.setPrizeId(prizeId);
                    opTreChestLogVo.setInteDrawTime(treChestLogVo.getInteDrawTime());
                    opTreChestLogVo.setIntegral(treChestLogVo.getIntegral());
                }
                if (prizeId == null) {
                    opTreChestLogVo.setPrizeName(OpTCEnum.NULL.getName());
                    opTreChestLogVo.setInteExp(treChestLogVo.getInteExp());
                    opTreChestLogVo.setInteDrawTime(treChestLogVo.getInteDrawTime());
                }
                opTreChestLogVos.add(opTreChestLogVo);
            }
        }
        //藏品抽奖记录
        if (drawMode.equals(OpTCEnum.NFTDRAWLOG.getValue())) {
            //根据活动标识和会员标识查询藏品抽奖记录
            QueryWrapper<OpNftDrawLog> opNftDrawLogQueryWrapper = new QueryWrapper<>();
            opNftDrawLogQueryWrapper.lambda().eq(OpNftDrawLog::getTreChestId, treId).eq(OpNftDrawLog::getMbId, mbId);
            List<OpNftDrawLogVo> opNftDrawLogVos = opNftDrawLogMapper.selectVoList(opNftDrawLogQueryWrapper);
            for (OpNftDrawLogVo opNftDrawLogVo : opNftDrawLogVos) {
                OpTreChestLogVo opTreChestLogVo = new OpTreChestLogVo();
                //查看本次活动所需消耗藏品信息
                QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
                opNftTreChestQueryWrapper.lambda().eq(OpNftTreChest::getTreChestId, treId);
                List<OpNftTreChestVo> opNftTreChestVos = opNftTreChestMapper.selectVoList(opNftTreChestQueryWrapper);
                for (OpNftTreChestVo opNftTreChestVo : opNftTreChestVos) {
                    //获取所需消耗的藏品标识
                    String nftId = opNftTreChestVo.getNftId();
                    //获取消耗藏品消耗数量
                    Integer nftExpQua = opNftTreChestVo.getNftExpQua();
                    //根据所需消耗的藏品标识获取藏品信息
                    DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                    //获取消耗藏品名称
                    String name = dcNftInfo.getName();
                    //获取消耗藏品封面
                    String cover = dcNftInfo.getCover();
                    opTreChestLogVo.setNftExpQua(nftExpQua);
                    opTreChestLogVo.setNftName(name);
                    opTreChestLogVo.setCover(cover);
                }
                //获取奖品标识
                String prizeId = opNftDrawLogVo.getPrizeId();
                if (prizeId != null) {
                    //根据奖品标识查出奖品的信息
                    DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(prizeId);
                    opTreChestLogVo.setPrizeName(dcNftInfo.getName());
                    opTreChestLogVo.setCover(dcNftInfo.getCover());
                    opTreChestLogVo.setPrizeId(prizeId);
                    opTreChestLogVo.setInteDrawTime(opNftDrawLogVo.getNftDrawTime());
                    opTreChestLogVo.setIntegral(opNftDrawLogVo.getNftCreId());
                }
                if (prizeId == null) {
                    opTreChestLogVo.setPrizeName(OpTCEnum.NULL.getName());
                    opTreChestLogVo.setInteDrawTime(opNftDrawLogVo.getNftDrawTime());
                }
                opTreChestLogVos.add(opTreChestLogVo);
            }
        }
        return opTreChestLogVos;
    }

    /**
     * 运营端查询此次活动的抽奖记录
     *
     * @param keyword  关键字
     * @param treId    宝箱活动标识
     * @param pageNo   当前页
     * @param pageSize 每页显示条数
     * @return 分页信息
     */
    @Override
    public Page<OpTreChestOpRemarkVo> queryDrawLog(String keyword, String treId, Integer pageNo, Integer pageSize) {
        //当前第几页至少为第一页
        if (pageNo <= 0) {
            pageNo = 1;
        }
        //每页显示条数至少为1条
        if (pageSize <= 0) {
            pageSize = 1;
        }
        Page<OpTreChestOpRemarkVo> opInteDrawLogPage = new Page<>(pageNo, pageSize);
        //根据宝箱活动标识获取宝箱活动信息
        OpTreChestInfo opTreChestInfo = mapper.selectById(treId);
        //抽奖方式
        Integer drawMode = opTreChestInfo.getDrawMode();
        //积分消耗
        Integer conInte = opTreChestInfo.getConInte();
        //积分抽奖记录
        if (drawMode.equals(OpTCEnum.INTEDRAWLOG.getValue())) {
            //查询此次活动所有的积分抽奖记录
            Page<OpTreChestOpRemarkVo> opTreChestOpRemarkVos = mapper.queryInte(opInteDrawLogPage, treId, keyword);
            List<OpTreChestOpRemarkVo> records = opTreChestOpRemarkVos.getRecords();
            for (OpTreChestOpRemarkVo opTreChestOpRemarkVo : records) {
                //根据会员标识查出会员用户名
                QueryWrapper<MbUserInfo> mbUserInfoQueryWrapper = new QueryWrapper<>();
                mbUserInfoQueryWrapper.lambda().eq(MbUserInfo::getId, opTreChestOpRemarkVo.getMbId());
                MbUserInfoVo mbUserInfoVo = iMbMemberMapper.selectVoOne(mbUserInfoQueryWrapper);
                //会员头像
                opTreChestOpRemarkVo.setUuidAvatar(mbUserInfoVo.getUuidAvatar());
                //设置会员用户名
                opTreChestOpRemarkVo.setUserName(mbUserInfoVo.getUserName());
                //设置宝箱活动标题
                opTreChestOpRemarkVo.setOpTitle(opTreChestInfo.getOpTitle());
                //设置抽奖方式
                opTreChestOpRemarkVo.setDrawMode(drawMode);
                //设置积分消耗
                opTreChestOpRemarkVo.setConInte(conInte);
                //设置活动标识
                opTreChestOpRemarkVo.setTreId(treId);
            }
        }
        //藏品抽奖记录
        if (drawMode.equals(OpTCEnum.NFTDRAWLOG.getValue())) {
            //查询此次活动所有的藏品抽奖记录
            Page<OpTreChestOpRemarkVo> opTreChestOpRemarkVos = mapper.queryNftDraw(opInteDrawLogPage, treId, keyword);
            List<OpTreChestOpRemarkVo> records = opTreChestOpRemarkVos.getRecords();
            for (OpTreChestOpRemarkVo opTreChestOpRemarkVo : records) {
                //根据会员标识查出会员用户名
                QueryWrapper<MbUserInfo> mbUserInfoQueryWrapper = new QueryWrapper<>();
                mbUserInfoQueryWrapper.lambda().eq(MbUserInfo::getId, opTreChestOpRemarkVo.getMbId());
                MbUserInfoVo mbUserInfoVo = iMbMemberMapper.selectVoOne(mbUserInfoQueryWrapper);
                //设置会员头像
                opTreChestOpRemarkVo.setUuidAvatar(mbUserInfoVo.getUuidAvatar());
                //设置会员用户名
                opTreChestOpRemarkVo.setUserName(mbUserInfoVo.getUserName());
                //设置宝箱活动标题
                opTreChestOpRemarkVo.setOpTitle(opTreChestInfo.getOpTitle());
                //查看本次活动所需消耗藏品信息
                QueryWrapper<OpNftTreChest> opNftTreChestQueryWrapper = new QueryWrapper<>();
                opNftTreChestQueryWrapper.lambda().eq(OpNftTreChest::getTreChestId, treId);
                List<OpNftTreChestVo> opNftTreChestVos = opNftTreChestMapper.selectVoList(opNftTreChestQueryWrapper);
                for (OpNftTreChestVo opNftTreChestVo : opNftTreChestVos) {
                    //根据消耗藏品的标识去查出藏品封面和名称
                    String nftId = opNftTreChestVo.getNftId();
                    //根据所需消耗的藏品标识获取藏品信息
                    DcNftInfo dcNftInfo = dcNftInfoMapper.selectById(nftId);
                    opNftTreChestVo.setNftName(dcNftInfo.getName());
                    opNftTreChestVo.setCover(dcNftInfo.getCover());
                    //设置藏品抽奖消耗信息
                    opTreChestOpRemarkVo.setOpNftTreChestVo(opNftTreChestVo);
                    //设置抽奖方式
                    opTreChestOpRemarkVo.setDrawMode(drawMode);
                    //设置活动标识
                    opTreChestOpRemarkVo.setTreId(treId);
                }
            }
        }
        return opInteDrawLogPage;
    }

    /**
     * 根据会员标识与藏品标识查出会员的藏品信息*
     *
     * @param mbId  会员标识
     * @param nftId 藏品标识
     * @return 藏品证书信息*
     */
    @Override
    public List<DcNftCertVo> getCertInfo(String mbId, String nftId) {
        //调用查询该会员所有此类的藏品mapper接口
        List<DcNftCertVo> dcNftCertVos = mapper.getCer(mbId, nftId);
        return dcNftCertVos;
    }
}
